home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ps / RCS / ps.c,v < prev    next >
Encoding:
Text File  |  1990-09-03  |  49.9 KB  |  2,119 lines

  1. head     1.22;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.22
  10. date     90.09.02.20.50.50;  author douglis;  state Exp;
  11. branches ;
  12. next     1.21;
  13.  
  14. 1.21
  15. date     90.09.01.18.24.57;  author douglis;  state Exp;
  16. branches ;
  17. next     1.20;
  18.  
  19. 1.20
  20. date     90.03.29.15.47.36;  author douglis;  state Exp;
  21. branches ;
  22. next     1.19;
  23.  
  24. 1.19
  25. date     89.11.09.12.44.10;  author mendel;  state Exp;
  26. branches ;
  27. next     1.18;
  28.  
  29. 1.18
  30. date     89.11.07.12.47.29;  author mendel;  state Exp;
  31. branches ;
  32. next     1.17;
  33.  
  34. 1.17
  35. date     89.07.31.17.50.44;  author douglis;  state Exp;
  36. branches ;
  37. next     1.16;
  38.  
  39. 1.16
  40. date     89.06.12.15.51.43;  author douglis;  state Exp;
  41. branches ;
  42. next     1.15;
  43.  
  44. 1.15
  45. date     89.03.24.16.01.07;  author ouster;  state Exp;
  46. branches ;
  47. next     1.14;
  48.  
  49. 1.14
  50. date     89.02.22.11.35.29;  author jhh;  state Exp;
  51. branches ;
  52. next     1.13;
  53.  
  54. 1.13
  55. date     88.12.22.11.04.48;  author douglis;  state Exp;
  56. branches ;
  57. next     1.12;
  58.  
  59. 1.12
  60. date     88.11.14.13.00.38;  author douglis;  state Exp;
  61. branches ;
  62. next     1.11;
  63.  
  64. 1.11
  65. date     88.10.17.17.47.55;  author douglis;  state Exp;
  66. branches ;
  67. next     1.10;
  68.  
  69. 1.10
  70. date     88.08.25.12.33.12;  author nelson;  state Exp;
  71. branches ;
  72. next     1.9;
  73.  
  74. 1.9
  75. date     88.08.07.14.57.22;  author ouster;  state Exp;
  76. branches ;
  77. next     1.8;
  78.  
  79. 1.8
  80. date     88.08.05.21.38.29;  author ouster;  state Exp;
  81. branches ;
  82. next     1.7;
  83.  
  84. 1.7
  85. date     88.08.05.18.23.04;  author ouster;  state Exp;
  86. branches ;
  87. next     1.6;
  88.  
  89. 1.6
  90. date     88.08.05.16.47.28;  author ouster;  state Exp;
  91. branches ;
  92. next     1.5;
  93.  
  94. 1.5
  95. date     88.08.05.16.13.52;  author ouster;  state Exp;
  96. branches ;
  97. next     1.4;
  98.  
  99. 1.4
  100. date     88.08.05.15.51.08;  author ouster;  state Exp;
  101. branches ;
  102. next     1.3;
  103.  
  104. 1.3
  105. date     88.08.05.14.53.26;  author ouster;  state Exp;
  106. branches ;
  107. next     1.2;
  108.  
  109. 1.2
  110. date     88.08.05.11.48.23;  author ouster;  state Exp;
  111. branches ;
  112. next     1.1;
  113.  
  114. 1.1
  115. date     88.08.01.17.12.05;  author ouster;  state Exp;
  116. branches ;
  117. next     ;
  118.  
  119.  
  120. desc
  121. @@
  122.  
  123.  
  124. 1.22
  125. log
  126. @fixed bug causing something like 
  127.  
  128.     Couldn't find migrated pid "24c31": the operation was successful.
  129.  
  130. to be printed
  131. @
  132. text
  133. @/* 
  134.  * ps.c --
  135.  *
  136.  *    This file contains a program that will print out process
  137.  *    status information for one or more processes.  See the
  138.  *    man page for details on what it does.
  139.  *
  140.  * Copyright 1988 Regents of the University of California
  141.  * Permission to use, copy, modify, and distribute this
  142.  * software and its documentation for any purpose and without
  143.  * fee is hereby granted, provided that the above copyright
  144.  * notice appear in all copies.  The University of California
  145.  * makes no representations about the suitability of this
  146.  * software for any purpose.  It is provided "as is" without
  147.  * express or implied warranty.
  148.  */
  149.  
  150. #ifndef lint
  151. static char rcsid[] = "$Header: /sprite/src/cmds/ps/RCS/ps.c,v 1.21 90/09/01 18:24:57 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  152. #endif not lint
  153.  
  154. #include <ctype.h>
  155. #include <hash.h>
  156. #include <host.h>
  157. #include <option.h>
  158. #include <proc.h>
  159. #include <pwd.h>
  160. #include <spriteTime.h>
  161. #include <status.h>
  162. #include <stdio.h>
  163. #include <stdlib.h>
  164. #include <string.h>
  165. #include <sys/ioctl.h>
  166. #include <vm.h>
  167.  
  168. /*
  169.  * Process status information may be printed in any of several ways,
  170.  * selected by command-line switches.  For each way there is a procedure
  171.  * that is called to print out in that format.  The following table
  172.  * identifies all such procedures:
  173.  */
  174.  
  175. extern void UpdateMigInfo();
  176. extern void PrintIDs(), PrintLong(), PrintMigration();
  177. extern void PrintShort(), PrintSignals(), PrintVM();
  178.  
  179. void (*(printProc[]))() = {
  180.     PrintShort,
  181.     PrintLong,
  182.     PrintIDs,
  183.     PrintVM,
  184.     PrintMigration,
  185.     PrintSignals,
  186. };
  187.  
  188. /*
  189.  * Indexes into printProc:
  190.  */
  191.  
  192. #define SHORT    0
  193. #define    LONG    1
  194. #define IDS    2
  195. #define VM    3
  196. #define MIG    4
  197. #define SIGS    5
  198.  
  199. int printIndex = 0;
  200.  
  201. /*
  202.  * Corresponding to each of the printing styles above, there is a
  203.  * corresponding sort procedure that is used as an argument to qsort
  204.  * in order to sort the process table entries in a particular way.
  205.  * 0 means don't sort:  just print them in table order.
  206.  */
  207.  
  208. extern int AgeSort(), UsageSort();
  209.  
  210. int (*(sortProc[]))() = {
  211.     AgeSort,
  212.     UsageSort,
  213.     0,
  214.     0,
  215.     0,
  216.     0
  217. };
  218.  
  219. /*
  220.  * Flags set by command-line options:
  221.  */
  222.  
  223. int aFlag =        0;    /* Non-zero means consider processes for
  224.                  * all users. */
  225. int AFlag =        0;    /* Non-zero means even consider dead procs. */
  226. int dFlag =        0;    /* Non-zero means only print info for
  227.                  * processes in debug state. */
  228. int kFlag =        0;    /* Non-zero means print out kernel processes
  229.                  * too. */
  230. int mFlag =        0;    /* Non-zero means only print out info for
  231.                  * processes in migrated state, or foreign
  232.                  * processes. */
  233. int lFlag =        0;    /* Non-zero means only print out local info for
  234.                  * migrated processes. */
  235. int lineWidth =        80;    /* Number of chars in each printed line. */
  236.  
  237. /*
  238.  * The table below describes the various command-line options that
  239.  * are understood by this program:
  240.  */
  241.  
  242. Option optionArray[] = {
  243.     OPT_DOC,        (char *) NULL,    (char *) NULL,
  244.         "This program prints out process status information.\n Synopsis:  \"ps [switches] [pid pid ...]\"\n Command-line switches are:",
  245.     OPT_TRUE,        "a",        (char *) &aFlag,
  246.         "Print info for all users' processes\n\t\tDefault: only current user's processes",
  247.     OPT_TRUE,        "A",        (char *) &AFlag,
  248.         "Print info for absolutely all user processes, even dead ones",
  249.     OPT_TRUE,        "d",        (char *) &dFlag,
  250.         "Print out only processes in DEBUG state",
  251.     OPT_CONSTANT(IDS),    "i",        (char *) &printIndex,
  252.         "Print out various process ids",
  253.     OPT_TRUE,        "k",        (char *) &kFlag,
  254.         "Print out kernel server processes as well as user processes",
  255.     OPT_TRUE,        "l",        (char *) &lFlag,
  256.         "Print out only local information for migrated processes",
  257.     OPT_TRUE,        "m",        (char *) &mFlag,
  258.         "Print out only processes that are foreign or migrated",
  259.     OPT_CONSTANT(SIGS),    "s",        (char *) &printIndex,
  260.         "Print out information about signals",
  261.     OPT_CONSTANT(LONG),    "u",        (char *) &printIndex,
  262.         "Print info in longer \"user-oriented\" form",
  263.     OPT_CONSTANT(VM),    "v",        (char *) &printIndex,
  264.         "Print virtual memory information",
  265.     OPT_INT,        "w",        (char *) &lineWidth,
  266.         "Next argument holds line width for output",
  267.     OPT_CONSTANT(MIG),    "M",        (char *) &printIndex,
  268.         "Print out migration information for migrated processes",
  269. };
  270.  
  271. /*
  272.  * The following type is used to associate a process control block an
  273.  * its argument string, so that during various sorts the two can be kept
  274.  * properly associated.
  275.  */
  276.  
  277. typedef struct {
  278.     Proc_PCBInfo *infoPtr;
  279.     Proc_PCBArgString *argString;
  280. } ControlBlock;
  281.  
  282. /*
  283.  * Miscellaneous global variables:
  284.  */
  285.  
  286. int lastPCB;        /* Set to non-zero before processing last
  287.              * control block (allows print procs to print
  288.              * totals, if they want). */
  289.  
  290. int pageSizeInKiloBytes; /* The size of the system's page in kilobytes. */
  291.  
  292. int     timerTicksPerSecond; 
  293.  
  294. /*
  295.  *----------------------------------------------------------------------
  296.  *
  297.  * main --
  298.  *
  299.  *    The main program for ps.
  300.  *
  301.  * Results:
  302.  *    None.
  303.  *
  304.  * Side effects:
  305.  *    Prints information on standard output.
  306.  *
  307.  *----------------------------------------------------------------------
  308.  */
  309.  
  310. main(argc, argv)
  311.     int argc;        /* Number of command-line arguments. */
  312.     char **argv;    /* Values of command-line arguments. */
  313. {
  314.     int i, pcbsUsed;
  315.     ReturnStatus status;
  316.     struct winsize winsize;
  317.  
  318.     pageSizeInKiloBytes = getpagesize()/1024;
  319.     timerTicksPerSecond = getTicksPerSecond();
  320.  
  321.     /*
  322.      * Find out how big the lines are, for formatting output, then
  323.      * parse options.
  324.      */
  325.  
  326.     if ((ioctl(fileno(stdout), TIOCGWINSZ, (char *) &winsize) == 0)
  327.         && (winsize.ws_col != 0)) {
  328.     lineWidth = winsize.ws_col;
  329.     } else {
  330.     char buf[1024];
  331.     char *termEnv;
  332.  
  333.     termEnv = getenv("TERM");
  334.     if (termEnv == 0) {
  335.         termEnv = "";
  336.     }
  337.     if (tgetent(buf, termEnv) == 1) {
  338.         i = tgetnum("co");
  339.         if (i > 0) {
  340.         lineWidth = i;
  341.         }
  342.     }
  343.     }
  344.  
  345.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray),
  346.         OPT_ALLOW_CLUSTERING);
  347.  
  348.     /*
  349.      * If particular process ids were given, then only print them.
  350.      * Otherwise look at all the processes in the system.
  351.      */
  352.  
  353.     if (argc > 1) {
  354.     for (i = 1; i < argc; i++) {
  355.         int pid;
  356.         Proc_PCBInfo info;
  357.         Proc_PCBInfo migInfo;
  358.         Proc_PCBArgString argString;
  359.         char *endPtr;
  360.  
  361.         pid = strtoul(argv[i], &endPtr, 16);
  362.         if (endPtr == argv[i]) {
  363.         fprintf(stderr, "Bad process id \"%s\";  ignoring.\n", argv[i]);
  364.         continue;
  365.         }
  366.         status = Proc_GetPCBInfo(Proc_PIDToIndex(pid),
  367.                      Proc_PIDToIndex(pid), PROC_MY_HOSTID,
  368.                      sizeof(info),
  369.                      &info, &argString, &pcbsUsed);
  370.         if (status != SUCCESS) {
  371.         fprintf(stderr, "Couldn't find pid \"%s\": %s.\n", argv[i],
  372.             Stat_GetMsg(status));
  373.         fflush(stderr);
  374.         continue;
  375.         }
  376.         /*
  377.          * The process we got info for may not be the one that was
  378.          * requested (different generation numbers);  check to be sure.
  379.          */
  380.  
  381.         if (pid != info.processID) {
  382.         fprintf(stderr, "Pid %s not found.\n", argv[i]);
  383.         continue;
  384.         }
  385.         if (printIndex != MIG && info.state == PROC_MIGRATED && !lFlag) {
  386.         status = Proc_GetPCBInfo(Proc_PIDToIndex(info.peerProcessID),
  387.                      Proc_PIDToIndex(info.peerProcessID),
  388.                      info.peerHostID,
  389.                      sizeof(migInfo), &migInfo, 
  390.                      (Proc_PCBArgString *) NULL,
  391.                      (int *) NULL);
  392.         if (status != SUCCESS || migInfo.state == PROC_UNUSED) {
  393.             /*
  394.              * Skip an entry that's migrated locally and doesn't
  395.              * exist remotely -- a race condition between the time
  396.              * we found out about the process and the time the process
  397.              * exited.  But if the status is not expected,
  398.              * print a warning message.
  399.              */
  400.             if (status != PROC_INVALID_PID && status != SUCCESS) {
  401.             fprintf(stderr, "Couldn't find migrated pid \"%x\": %s.\n",
  402.                 info.peerProcessID, Stat_GetMsg(status));
  403.             }
  404.             continue;
  405.         } else {
  406.             UpdateMigInfo(&migInfo, &info);
  407.         }
  408.         }
  409.         if (i == (argc-1)) {
  410.         lastPCB = 1;
  411.         }
  412.         (*(printProc[printIndex]))(&info, &argString);
  413.     }
  414.     } else {
  415. #define NUM_PCBS 256
  416.     Proc_PCBInfo infos[NUM_PCBS];
  417.     Proc_PCBInfo migInfo;
  418.     ControlBlock blocks[NUM_PCBS];
  419.     Proc_PCBArgString argStrings[NUM_PCBS];
  420.     int numToPrint, uid;
  421.     register Proc_PCBInfo *infoPtr;
  422.  
  423.     /*
  424.      * Dump the entire process table into our memory.
  425.      */
  426.  
  427.     status = Proc_GetPCBInfo(0, NUM_PCBS-1, PROC_MY_HOSTID,
  428.                  sizeof(Proc_PCBInfo),
  429.                  infos, argStrings, &pcbsUsed);
  430.     if (status != SUCCESS) {
  431.         fprintf(stderr, "Couldn't read process table: %s\n",
  432.             Stat_GetMsg(status));
  433.         exit(1);
  434.     }
  435.  
  436.     /*
  437.      * Collect info into blocks suitable for sorting.  Along the way,
  438.      * filter out irrelevant processes.
  439.      */
  440.  
  441.     uid = geteuid();
  442.     for (i = 0, numToPrint = 0, infoPtr = infos; i < pcbsUsed;
  443.         i++, infoPtr++) {
  444.         if (infoPtr->state == PROC_UNUSED) {
  445.         if (!AFlag) {
  446.             continue;
  447.         }
  448.         goto keepThisProc;
  449.         }
  450.         if (infoPtr->genFlags & PROC_KERNEL) {
  451.         if (!kFlag) {
  452.             continue;
  453.         }
  454.         goto keepThisProc;
  455.         }
  456.         if ((!aFlag) && (uid != infoPtr->effectiveUserID)) {
  457.            continue;
  458.         }
  459.         if (dFlag) {
  460.         if ((infoPtr->state != PROC_SUSPENDED) || !(infoPtr->genFlags
  461.             & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST))) {
  462.             continue;
  463.         }
  464.         }
  465.         if (mFlag &&
  466.         !((infoPtr->genFlags & PROC_FOREIGN)
  467.           || (infoPtr->state == PROC_MIGRATED))) {
  468.         continue;
  469.         }
  470.  
  471.         keepThisProc:
  472.         /*
  473.          * When not printing migration info, follow migrated processes.
  474.          */
  475.         if (printIndex != MIG &&  infoPtr->state == PROC_MIGRATED &&
  476.         !lFlag) {
  477.         status = Proc_GetPCBInfo(Proc_PIDToIndex(infoPtr->peerProcessID),
  478.                      Proc_PIDToIndex(infoPtr->peerProcessID),
  479.                      infoPtr->peerHostID,
  480.                      sizeof(migInfo), &migInfo, 
  481.                      (Proc_PCBArgString *) NULL,
  482.                      (int *) NULL);
  483.         if (status != SUCCESS || migInfo.state == PROC_UNUSED) {
  484.             /*
  485.              * Skip an entry that's migrated locally and doesn't
  486.              * exist remotely -- a race condition between the time
  487.              * we found out about the process and the time the process
  488.              * exited.
  489.              */
  490.             if (status != PROC_INVALID_PID && status != SUCCESS) {
  491.             fprintf(stderr, "Couldn't find migrated pid \"%x\": %s.\n",
  492.                 infoPtr->peerProcessID, Stat_GetMsg(status));
  493.             }
  494.             continue;
  495.         } else {
  496.             UpdateMigInfo(&migInfo, infoPtr);
  497.         }
  498.         }
  499.         blocks[numToPrint].infoPtr = infoPtr;
  500.         blocks[numToPrint].argString = &argStrings[i];
  501.         numToPrint++;
  502.     }
  503.  
  504.     /*
  505.          * Sort the processes, if a sorting procedure has been supplied.
  506.      */
  507.  
  508.     if (sortProc[printIndex] != 0) {
  509.         qsort((char *) blocks, numToPrint, sizeof(ControlBlock),
  510.             sortProc[printIndex]);
  511.     }
  512.  
  513.     /*
  514.      * Print them out in order.
  515.      */
  516.  
  517.     for (i = 0; i < numToPrint; i++) {
  518.         if (i == (numToPrint-1)) {
  519.         lastPCB = 1;
  520.         }
  521.         (*(printProc[printIndex]))(blocks[i].infoPtr, blocks[i].argString);
  522.     }
  523.     }
  524.     exit(0);
  525. }
  526.  
  527. /*
  528.  *----------------------------------------------------------------------
  529.  *
  530.  * UpdateMigInfo --
  531.  *
  532.  *    Update relevant information for a migrated process using the
  533.  *    PCB info obtained from its current host.
  534.  *
  535.  * Results:
  536.  *    None.
  537.  *
  538.  * Side effects:
  539.  *    Fields are copied from one structure to the other.
  540.  *
  541.  *----------------------------------------------------------------------
  542.  */
  543.  
  544. void
  545. UpdateMigInfo(migPtr, infoPtr)
  546.     Proc_PCBInfo *migPtr;    /* Pointer to control block on current host. */
  547.     Proc_PCBInfo *infoPtr;    /* Pointer to control block on this host. */
  548. {
  549.     register int i;
  550.     
  551.     infoPtr->processor = migPtr->processor;
  552.     infoPtr->state = migPtr->state;    
  553.     infoPtr->genFlags = migPtr->genFlags;
  554.     infoPtr->event = migPtr->event;
  555.     infoPtr->billingRate = migPtr->billingRate;
  556.     infoPtr->recentUsage = migPtr->recentUsage;
  557.     infoPtr->weightedUsage = migPtr->weightedUsage;
  558.     infoPtr->unweightedUsage = migPtr->unweightedUsage;
  559.     infoPtr->kernelCpuUsage = migPtr->kernelCpuUsage;
  560.     infoPtr->userCpuUsage = migPtr->userCpuUsage;
  561.     infoPtr->childKernelCpuUsage = migPtr->childKernelCpuUsage;
  562.     infoPtr->childUserCpuUsage = migPtr->childUserCpuUsage;
  563.     infoPtr->numQuantumEnds = migPtr->numQuantumEnds;
  564.     infoPtr->numWaitEvents = migPtr->numWaitEvents;
  565.     infoPtr->schedQuantumTicks = migPtr->schedQuantumTicks;
  566.     for (i = 0; i < VM_NUM_SEGMENTS; i++) {
  567.     infoPtr->vmSegments[i] = migPtr->vmSegments[i];
  568.     }
  569.     infoPtr->sigHoldMask = migPtr->sigHoldMask;
  570.     infoPtr->sigPendingMask = migPtr->sigPendingMask;
  571.     for (i = 0; i < SIG_NUM_SIGNALS; i++) {
  572.     infoPtr->sigActions[i] = migPtr->sigActions[i];
  573.     }
  574. }
  575.  
  576. /*
  577.  *----------------------------------------------------------------------
  578.  *
  579.  * TimeString --
  580.  *
  581.  *    Given a process control block, return a string indicating how
  582.  *    much CPU time the process has used up.
  583.  *
  584.  * Results:
  585.  *    The return value is a statically-allocated string that holds
  586.  *    the time used by the process, in the format min:sec.
  587.  *
  588.  * Side effects:
  589.  *    None.
  590.  *
  591.  *----------------------------------------------------------------------
  592.  */
  593.  
  594. char *
  595. TimeString(infoPtr)
  596.     Proc_PCBInfo *infoPtr;    /* Pointer to control block. */
  597. {
  598.     Time sum;
  599.     static char result[20];
  600.  
  601.     Time_Add(infoPtr->userCpuUsage, infoPtr->kernelCpuUsage, &sum);
  602.     if (sum.microseconds >= 500000) {
  603.     sum.seconds += 1;
  604.     }
  605.     sprintf(result, "%d:%02d", sum.seconds/60, sum.seconds%60);
  606.     return result;
  607. }
  608.  
  609. /*
  610.  *----------------------------------------------------------------------
  611.  *
  612.  * StateString --
  613.  *
  614.  *    Given a process control block, return a string describing
  615.  *    the process's current execution state.
  616.  *
  617.  * Results:
  618.  *    The return value is a statically-allocated string that describes
  619.  *    the process's state.
  620.  *
  621.  * Side effects:
  622.  *    None.
  623.  *
  624.  *----------------------------------------------------------------------
  625.  */
  626.  
  627. char *
  628. StateString(infoPtr)
  629.     Proc_PCBInfo *infoPtr;    /* Pointer to control block. */
  630. {
  631.     switch (infoPtr->state) {
  632.     case PROC_UNUSED:
  633.         return "UNUSD";
  634.         break;
  635.     case PROC_RUNNING:
  636.         return "RUN  ";
  637.         break;
  638.     case PROC_READY:
  639.         return "READY";
  640.         break;
  641.     case PROC_WAITING:
  642.         if (infoPtr->event == -1) {
  643.         return "RWAIT";
  644.         } else {
  645.         return "WAIT ";
  646.         }
  647.         break;
  648.     case PROC_EXITING:
  649.         return "EXIT ";
  650.         break;
  651.     case PROC_DEAD:
  652.         return "DEAD ";
  653.         break;
  654.     case PROC_MIGRATING:
  655.         return "->MIG";
  656.         break;
  657.     case PROC_MIGRATED:
  658.         return "MIG  ";
  659.         break;
  660.     case PROC_NEW:
  661.         return "NEW  ";
  662.         break;
  663.     case PROC_SUSPENDED:
  664.         if (infoPtr->genFlags & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST)) {
  665.         return "DEBUG";
  666.         } else {
  667.         return "SUSP ";
  668.         }
  669.         break;
  670.     }
  671.     return "?Huh?";
  672. }
  673.  
  674. /*
  675.  *----------------------------------------------------------------------
  676.  *
  677.  * PriString --
  678.  *
  679.  *    Given a process's billing rate, return a string describing
  680.  *    the process's priority.
  681.  *
  682.  * Results:
  683.  *    The return value is a statically-allocated string that describes
  684.  *    the process's priority.
  685.  *
  686.  * Side effects:
  687.  *    None.
  688.  *
  689.  *----------------------------------------------------------------------
  690.  */
  691.  
  692. char *
  693. PriString(billingRate)
  694.     int billingRate;    /* process's kernel billing rate. */
  695. {
  696.     /*
  697.      * The default billing rate is 0.  Predefined constants are set up
  698.      * for -2 to 2.  2 is for servers and means they are not billed at all.
  699.      */
  700.     switch (billingRate) {
  701.     case 0:
  702.         return("");
  703.     case -1:
  704.         return("<");
  705.     case 1:
  706.         return(">");
  707.     case 2:
  708.         return("S");
  709.     case -2:
  710.         return("<<");
  711.     default: {
  712.         if (billingRate > 2) {
  713.         return("S");
  714.         }
  715.         return("<<");
  716.     }
  717.  
  718.     }
  719. }
  720.  
  721. /*
  722.  *----------------------------------------------------------------------
  723.  *
  724.  * ArgString --
  725.  *
  726.  *    Given an argument string for a command, modifies the string
  727.  *    to fit the line width for output.
  728.  *
  729.  * Results:
  730.  *    The return value is a pointer to the argument string.
  731.  *
  732.  * Side effects:
  733.  *    The argument string may be shortened by chopping off characters
  734.  *    and adding "...", if it is too long to fit on a single output line.
  735.  *
  736.  *----------------------------------------------------------------------
  737.  */
  738.  
  739. char *
  740. ArgString(argPtr, colsTaken)
  741.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  742.                  * process. */
  743.     int colsTaken;        /* Number of output columns already taken up
  744.                  * by other printed information. */
  745. {
  746.     int charsToKeep;
  747.     char *arg;
  748.     register char *p;
  749.  
  750.     arg = argPtr->argString;
  751.     charsToKeep = lineWidth - colsTaken;
  752.     if (charsToKeep < 10) {
  753.     charsToKeep = 10;
  754.     }
  755.     if (strlen(arg) <= charsToKeep) {
  756.     return arg;
  757.     }
  758.  
  759.     /*
  760.      * Chop fields off the command line until reaching something that fits
  761.      * within the line and leaves enough space for an ellipsis.  If not even
  762.      * the command name fits, then print a partial field.
  763.      */
  764.  
  765.     for (p = arg+charsToKeep-4; p > arg; p--) {
  766.     if (isspace(*p)) {
  767.         break;
  768.     }
  769.     }
  770.     if (p == arg) {
  771.     p = arg+charsToKeep-3;
  772.     } else {
  773.     for (p--; isspace(*p); p--) {
  774.         /* Null loop body;  just back over extra spaces. */
  775.     }
  776.     p += 2;
  777.     }
  778.     p[0] = '.';
  779.     p[1] = '.';
  780.     p[2] = '.';
  781.     p[3] = 0;
  782.     return arg;
  783. }
  784.  
  785. /*
  786.  *----------------------------------------------------------------------
  787.  *
  788.  * UserString --
  789.  *
  790.  *    Given a user id, return a string identifying the user.
  791.  *
  792.  * Results:
  793.  *    The return value is a pointer to a statically-allocated
  794.  *    string identifying the user.
  795.  *
  796.  * Side effects:
  797.  *    User information gets cached in a hash table.
  798.  *
  799.  *----------------------------------------------------------------------
  800.  */
  801.  
  802. char *
  803. UserString(uid)
  804.     int uid;            /* User id to find name for. */
  805. {
  806.     static Hash_Table table;
  807.     static int init = 0;
  808.     char *result;
  809.     register Hash_Entry *entry;
  810.     register struct passwd *passwd;
  811.     int new;
  812.  
  813.     if (!init) {
  814.     init = 1;
  815.     Hash_InitTable(&table, -1, HASH_ONE_WORD_KEYS);
  816.     }
  817.  
  818.     /*
  819.      * See if we've already looked up this process id.
  820.      */
  821.  
  822.     entry = Hash_CreateEntry(&table, (Address) uid, &new);
  823.     if (!new) {
  824.     return (char *) Hash_GetValue(entry);
  825.     }
  826.  
  827.     /*
  828.      * Never heard of this process id before.  Look it up in the
  829.      * password file and fill in the hash table entry.
  830.      */
  831.  
  832.     passwd = getpwuid(uid);
  833.     if (passwd == NULL) {
  834.     result = "???";
  835.     } else {
  836.     result = malloc((unsigned) (strlen(passwd->pw_name) + 1));
  837.     strcpy(result, passwd->pw_name);
  838.     }
  839.     Hash_SetValue(entry, result);
  840.     return result;
  841. }
  842.  
  843. /*
  844.  *----------------------------------------------------------------------
  845.  *
  846.  * HostString --
  847.  *
  848.  *    Given a host id, return a string identifying the host.
  849.  *
  850.  * Results:
  851.  *    The return value is a pointer to a statically-allocated
  852.  *    string identifying the host.
  853.  *
  854.  * Side effects:
  855.  *    Host information gets cached in a hash table.
  856.  *
  857.  *----------------------------------------------------------------------
  858.  */
  859.  
  860. char *
  861. HostString(hostID)
  862.     int hostID;            /* Host id to find name for. */
  863. {
  864.     static Hash_Table table;
  865.     static int init = 0;
  866.     char *result, *name;
  867.     register Hash_Entry *entry;
  868.     register Host_Entry *hostPtr;
  869.     char storage[20];
  870.     int new;
  871.  
  872.     if (!init) {
  873.     init = 1;
  874.     Hash_InitTable(&table, -1, HASH_ONE_WORD_KEYS);
  875.     }
  876.  
  877.     /*
  878.      * See if we've already looked up this host id.
  879.      */
  880.  
  881.     entry = Hash_CreateEntry(&table, (Address) hostID, &new);
  882.     if (!new) {
  883.     return (char *) Hash_GetValue(entry);
  884.     }
  885.  
  886.     /*
  887.      * Never heard of this host before.  Look it up in the
  888.      * host file and fill in the hash table entry.
  889.      */
  890.  
  891.     hostPtr = Host_ByID(hostID);
  892.     if (hostPtr == NULL) {
  893.     name = sprintf(storage, "%d", hostID);
  894.     } else {
  895.     if (hostPtr->aliases[0] != NULL) {
  896.         name = hostPtr->aliases[0];
  897.     } else {
  898.         name = hostPtr->name;
  899.     }
  900.     }
  901.     result = malloc((unsigned) (strlen(name) + 1));
  902.     strcpy(result, name);
  903.     Hash_SetValue(entry, result);
  904.     return result;
  905. }
  906.  
  907. /*
  908.  *----------------------------------------------------------------------
  909.  *
  910.  * PctCpuString --
  911.  *
  912.  *    Given an process table entry, return a string indicating what
  913.  *    fraction of recent CPU time has gone to this process.
  914.  *
  915.  * Results:
  916.  *    The return value is a pointer to a statically-allocated
  917.  *    string in the form "xx.y".  The string will change on the
  918.  *    next call to this procedure.
  919.  *
  920.  * Side effects:
  921.  *    None.
  922.  *
  923.  *----------------------------------------------------------------------
  924.  */
  925.  
  926. char *
  927. PctCpuString(infoPtr)
  928.     Proc_PCBInfo *infoPtr;    /* Pointer to control block. */
  929. {
  930.     static char result[10];
  931.     static int init = 0;
  932.     static double scaleFactor;
  933.     double percent;
  934.  
  935.     /*
  936.      * WARNING:  the following definitions must match the corresponding
  937.      * definitions in the kernel's file "schedule.c".
  938.      */
  939.  
  940. #define FORGET_MULTIPLY 14
  941. #define FORGET_SHIFT   4
  942.  
  943.     if (!init) {
  944.     int denom;
  945.  
  946.     init = 1;
  947.     scaleFactor = timerTicksPerSecond;
  948.     denom = 1<<FORGET_SHIFT;
  949.     scaleFactor *= denom;
  950.     scaleFactor /= denom-FORGET_MULTIPLY;
  951.     }
  952.  
  953.     percent = infoPtr->unweightedUsage;
  954.     percent = percent*100.0/scaleFactor;
  955.     sprintf(result, "%4.1f", percent);
  956.     return result;
  957. }
  958.  
  959. /*
  960.  *----------------------------------------------------------------------
  961.  *
  962.  * PrintShort --
  963.  *
  964.  *    This procedure is called to print out process information
  965.  *    in the "short" format.
  966.  *
  967.  * Results:
  968.  *    None.
  969.  *
  970.  * Side effects:
  971.  *    Prints info on standard output.
  972.  *
  973.  *----------------------------------------------------------------------
  974.  */
  975.  
  976. void
  977. PrintShort(infoPtr, argPtr)
  978.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  979.                  * info to be printed. */
  980.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  981.                  * process. */
  982. {
  983.     static int firstTime = 1;
  984.  
  985.     if (firstTime) {
  986.     firstTime = 0;
  987.     printf("PID   STATE   TIME COMMAND\n");
  988.     }
  989.     printf("%5x %s%7s %s\n", infoPtr->processID, StateString(infoPtr),
  990.         TimeString(infoPtr), ArgString(argPtr, 20));
  991. }
  992.  
  993. /*
  994.  *----------------------------------------------------------------------
  995.  *
  996.  * PrintLong --
  997.  *
  998.  *    This procedure is called to print out process information
  999.  *    in the "long" format (requested with the -u switch).
  1000.  *
  1001.  * Results:
  1002.  *    None.
  1003.  *
  1004.  * Side effects:
  1005.  *    Prints info on standard output.
  1006.  *
  1007.  *----------------------------------------------------------------------
  1008.  */
  1009.  
  1010. void
  1011. PrintLong(infoPtr, argPtr)
  1012.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  1013.                  * info to be printed. */
  1014.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  1015.                  * process. */
  1016. {
  1017.     static int firstTime = 1;
  1018.     Vm_Stat vmStat;
  1019.     Vm_SegmentInfo segBuf[VM_NUM_SEGMENTS];
  1020.     ReturnStatus status;
  1021.     int rss, size;
  1022.     double pctMem;
  1023.  
  1024.     if (firstTime) {
  1025.     firstTime = 0;
  1026.     printf("USER     PID   %%CPU %%MEM  SIZE   RSS STATE   TIME PR COMMAND\n");
  1027.     status = Vm_Cmd(VM_GET_STATS, &vmStat);
  1028.     if (status != SUCCESS) {
  1029.         fprintf(stderr, "Couldn't read Vm statistics: %s\n",
  1030.             Stat_GetMsg(status));
  1031.         exit(1);
  1032.     }
  1033.     }
  1034.     if (infoPtr->genFlags & PROC_KERNEL) {
  1035.     rss = size = 0;
  1036.     } else {
  1037.     status = Vm_GetSegInfo(infoPtr, 0, sizeof(Vm_SegmentInfo), 
  1038.                       &(segBuf[1]));
  1039.     switch(status) {
  1040.         case SUCCESS:
  1041.         rss = segBuf[VM_CODE].resPages + segBuf[VM_HEAP].resPages
  1042.             + segBuf[VM_STACK].resPages;
  1043.         size = segBuf[VM_CODE].numPages + segBuf[VM_HEAP].numPages
  1044.             + segBuf[VM_STACK].numPages;
  1045.         break;
  1046.         case SYS_INVALID_ARG:
  1047.         rss = -1;
  1048.         break;
  1049.         default: 
  1050.         fprintf(stderr, "Couldn't read segment info for pid %x: %s\n",
  1051.             infoPtr->processID, Stat_GetMsg(status));
  1052.         return;
  1053.     }
  1054.     }
  1055.     if (status == SUCCESS) {
  1056.     pctMem = rss;
  1057.     rss *= pageSizeInKiloBytes;
  1058.     size *= pageSizeInKiloBytes;
  1059.     pctMem = (pctMem*100.0)/vmStat.numPhysPages;
  1060.     printf("%-8.8s %5x %.8s %4.1f%6d%6d %s%7s %2s %s\n",
  1061.         UserString(infoPtr->effectiveUserID),
  1062.         infoPtr->processID, PctCpuString(infoPtr), pctMem, size, rss,
  1063.         StateString(infoPtr), TimeString(infoPtr),
  1064.            PriString(infoPtr->billingRate), ArgString(argPtr, 53));
  1065.     } else {
  1066.     printf("%-8.8s %5x %.8s %4s%6s%6s %s%7s %2s %s\n",
  1067.         UserString(infoPtr->effectiveUserID),
  1068.         infoPtr->processID, PctCpuString(infoPtr),"---","---","---",
  1069.         StateString(infoPtr), TimeString(infoPtr), 
  1070.         PriString(infoPtr->billingRate), ArgString(argPtr, 53));
  1071.     }
  1072. }
  1073.  
  1074. /*
  1075.  *----------------------------------------------------------------------
  1076.  *
  1077.  * PrintIDs --
  1078.  *
  1079.  *    This procedure is called to print out process information
  1080.  *    in the form of various ids.
  1081.  *
  1082.  * Results:
  1083.  *    None.
  1084.  *
  1085.  * Side effects:
  1086.  *    Prints info on standard output.
  1087.  *
  1088.  *----------------------------------------------------------------------
  1089.  */
  1090.  
  1091. void
  1092. PrintIDs(infoPtr, argPtr)
  1093.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  1094.                  * info to be printed. */
  1095.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  1096.                  * process. */
  1097. {
  1098.     static int firstTime = 1;
  1099.     char storage[10];
  1100.     char *family;
  1101.  
  1102.     if (firstTime) {
  1103.     firstTime = 0;
  1104.     printf("PID   PPID  GROUP USER     RUSER      TIME COMMAND\n");
  1105.     }
  1106.     if (infoPtr->familyID == -1) {
  1107.     family = "   -1";
  1108.     } else {
  1109.     family = sprintf(storage, "%5x", infoPtr->familyID);
  1110.     }
  1111.     printf("%5x %5x %s %-8.8s %-8.8s%7s %s\n",
  1112.         infoPtr->processID, infoPtr->parentID, family,
  1113.         UserString(infoPtr->effectiveUserID), 
  1114.         UserString(infoPtr->userID), TimeString(infoPtr),
  1115.         ArgString(argPtr, 43));
  1116. }
  1117.  
  1118. /*
  1119.  *----------------------------------------------------------------------
  1120.  *
  1121.  * PrintVM --
  1122.  *
  1123.  *    This procedure is called to print out vm-related information
  1124.  *    for processes.
  1125.  *
  1126.  * Results:
  1127.  *    None.
  1128.  *
  1129.  * Side effects:
  1130.  *    Prints info on standard output.
  1131.  *
  1132.  *----------------------------------------------------------------------
  1133.  */
  1134.  
  1135. void
  1136. PrintVM(infoPtr, argPtr)
  1137.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  1138.                  * info to be printed. */
  1139.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  1140.                  * process. */
  1141. {
  1142.     static int firstTime = 1;
  1143.     static int sizes[VM_NUM_SEGMENTS], rss[VM_NUM_SEGMENTS];
  1144.     static char *names[] = {"system", "code", "heap", "stack"};
  1145.     int totalSize, totalRss, i;
  1146.     Vm_SegmentInfo segBuf[VM_NUM_SEGMENTS];
  1147.     ReturnStatus status;
  1148. #define TOTAL_SEGS 256
  1149.     char segSeen[TOTAL_SEGS];
  1150.  
  1151.     if (firstTime) {
  1152.     firstTime = 0;
  1153.     printf("PID   CODSZ CODRS  HPSZ  HPRS STKSZ STKRS  SIZE   RSS COMMAND\n");
  1154.     }
  1155.  
  1156.     /*
  1157.      * Kernel processes have no memory, so skip them.
  1158.      */
  1159.  
  1160.     if (infoPtr->genFlags & PROC_KERNEL) {
  1161.     return;
  1162.     }
  1163.     status = Vm_GetSegInfo(infoPtr, 0, sizeof(Vm_SegmentInfo), &(segBuf[1]));
  1164.     if (status == SYS_INVALID_ARG) {
  1165.     totalSize = -1;
  1166.     } else if (status != SUCCESS) {
  1167.     fprintf(stderr, "Couldn't read segment info for pid %x: %s\n",
  1168.         infoPtr->processID, Stat_GetMsg(status));
  1169.     return;
  1170.     }
  1171.     if (status == SUCCESS) {
  1172.     totalSize = totalRss = 0;
  1173.     for (i = VM_CODE; i < VM_NUM_SEGMENTS; i++) {
  1174.         totalSize += segBuf[i].numPages*(pageSizeInKiloBytes);
  1175.         totalRss += segBuf[i].resPages*(pageSizeInKiloBytes);
  1176.         if (segBuf[i].segNum >= TOTAL_SEGS) {
  1177.         fprintf(stderr, "Pid %x has %s segment %d:  too large.\n",
  1178.             infoPtr->processID, names[i], segBuf[i].segNum);
  1179.         continue;
  1180.         }
  1181.         if (segSeen[segBuf[i].segNum]) {
  1182.         continue;
  1183.         }
  1184.         segSeen[segBuf[i].segNum] = 1;
  1185.         sizes[i] += segBuf[i].numPages*(pageSizeInKiloBytes);
  1186.         rss[i] += segBuf[i].resPages*(pageSizeInKiloBytes);
  1187.     }
  1188.     printf("%5x%6d%6d%6d%6d%6d%6d%6d%6d %s\n",
  1189.         infoPtr->processID,
  1190.         segBuf[VM_CODE].numPages*(pageSizeInKiloBytes),
  1191.         segBuf[VM_CODE].resPages*(pageSizeInKiloBytes),
  1192.         segBuf[VM_HEAP].numPages*(pageSizeInKiloBytes),
  1193.         segBuf[VM_HEAP].resPages*(pageSizeInKiloBytes),
  1194.         segBuf[VM_STACK].numPages*(pageSizeInKiloBytes),
  1195.         segBuf[VM_STACK].resPages*(pageSizeInKiloBytes),
  1196.         totalSize, totalRss, ArgString(argPtr, 54));
  1197.     } else {
  1198.     printf("%5x%6s%6s%6s%6s%6s%6s%6s%6s %s\n",
  1199.         infoPtr->processID,"---","---","---","---","---","---",
  1200.         "---","---", ArgString(argPtr, 54));
  1201.     }
  1202.     if (lastPCB) {
  1203.     printf("-----------------------------------------------------\n");
  1204.     printf("Total%6d%6d%6d%6d%6d%6d%6d%6d\n",
  1205.         sizes[VM_CODE], rss[VM_CODE], sizes[VM_HEAP], rss[VM_HEAP],
  1206.         sizes[VM_STACK], rss[VM_STACK],
  1207.         sizes[VM_CODE] + sizes[VM_HEAP] + sizes[VM_STACK],
  1208.         rss[VM_CODE] + rss[VM_HEAP] + rss[VM_STACK]);
  1209.     }
  1210. }
  1211.  
  1212. /*
  1213.  *----------------------------------------------------------------------
  1214.  *
  1215.  * PrintMigration --
  1216.  *
  1217.  *    This procedure is called to print out migration-related information
  1218.  *    for processes.
  1219.  *
  1220.  * Results:
  1221.  *    None.
  1222.  *
  1223.  * Side effects:
  1224.  *    Prints info on standard output.
  1225.  *
  1226.  *----------------------------------------------------------------------
  1227.  */
  1228.  
  1229. void
  1230. PrintMigration(infoPtr, argPtr)
  1231.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  1232.                  * info to be printed. */
  1233.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  1234.                  * process. */
  1235. {
  1236.     static int firstTime = 1;
  1237.  
  1238.     if (firstTime) {
  1239.     firstTime = 0;
  1240.     printf("PID   STATE   FLAGS    EVENT RNODE       RPID COMMAND\n");
  1241.     }
  1242.     if ((infoPtr->genFlags & PROC_FOREIGN)
  1243.         || (infoPtr->state == PROC_MIGRATED)) {
  1244.     printf("%5x %s%8x %8x %-10.10s %5x %s\n",
  1245.         infoPtr->processID, StateString(infoPtr),
  1246.         infoPtr->genFlags, infoPtr->event,
  1247.         HostString(infoPtr->peerHostID),
  1248.         infoPtr->peerProcessID,
  1249.         ArgString(argPtr, 46));
  1250.     } else {
  1251.     printf("%5x %s%8x %8x                  %s\n",
  1252.         infoPtr->processID, StateString(infoPtr),
  1253.         infoPtr->genFlags, infoPtr->event,
  1254.         ArgString(argPtr, 46));
  1255.     }
  1256. }
  1257.  
  1258. /*
  1259.  *----------------------------------------------------------------------
  1260.  *
  1261.  * PrintSignals --
  1262.  *
  1263.  *    This procedure is called to print out signal-related information
  1264.  *    for processes.
  1265.  *
  1266.  * Results:
  1267.  *    None.
  1268.  *
  1269.  * Side effects:
  1270.  *    Prints info on standard output.
  1271.  *
  1272.  *----------------------------------------------------------------------
  1273.  */
  1274.  
  1275. void
  1276. PrintSignals(infoPtr, argPtr)
  1277.     Proc_PCBInfo *infoPtr;    /* Pointer to control block containing
  1278.                  * info to be printed. */
  1279.     Proc_PCBArgString *argPtr;    /* Pointer to info about command line for
  1280.                  * process. */
  1281. {
  1282.     static int firstTime = 1;
  1283.     int ignore, handle, i;
  1284.  
  1285.     if (firstTime) {
  1286.     firstTime = 0;
  1287.     printf("PID    PENDING     HELD   IGNORE   HANDLE COMMAND\n");
  1288.     }
  1289.  
  1290.     ignore = handle = 0;
  1291.     for (i = 1; i <= SIG_NUM_SIGNALS; i++) {
  1292.     if (infoPtr->sigActions[i] == SIG_IGNORE_ACTION) {
  1293.         ignore |= 1<<(i-1);
  1294.     } else if (infoPtr->sigActions[i] >> SIG_NUM_ACTIONS) {
  1295.         handle |= 1<<(i-1);
  1296.     }
  1297.     }
  1298.     printf("%5x %8x %8x %8x %8x %s\n", infoPtr->processID,
  1299.         infoPtr->sigPendingMask, infoPtr->sigHoldMask,
  1300.         ignore, handle, ArgString(argPtr, 42));
  1301. }
  1302.  
  1303. /*
  1304.  *----------------------------------------------------------------------
  1305.  *
  1306.  * UsageSort --
  1307.  *
  1308.  *    This procedure is called while sorting the process table
  1309.  *    entries.  It returns a value that will sort the processes
  1310.  *    in decreasing order of recent CPU usage.
  1311.  *
  1312.  * Results:
  1313.  *    Returns < 0 if first's usage is > second's usage, >0 otherwise.
  1314.  *
  1315.  * Side effects:
  1316.  *    None.
  1317.  *
  1318.  *----------------------------------------------------------------------
  1319.  */
  1320.  
  1321. int
  1322. UsageSort(first, second)
  1323.     ControlBlock *first, *second;    /* Two PCBs to compare. */
  1324. {
  1325.     int i;
  1326.     i = second->infoPtr->unweightedUsage - first->infoPtr->unweightedUsage;
  1327.     return i;
  1328. }
  1329.  
  1330. /*
  1331.  *----------------------------------------------------------------------
  1332.  *
  1333.  * AgeSort --
  1334.  *
  1335.  *    This procedure is called while sorting the process table
  1336.  *    entries.  It attempts to return a value that will sort
  1337.  *    processes by age.
  1338.  *
  1339.  * Results:
  1340.  *    Returns < 0 if first is older than second.
  1341.  *
  1342.  * Side effects:
  1343.  *    None.
  1344.  *
  1345.  *----------------------------------------------------------------------
  1346.  */
  1347.  
  1348. int
  1349. AgeSort(first, second)
  1350.     ControlBlock *first, *second;    /* Two PCBs to compare. */
  1351. {
  1352. #ifdef NOTDEF
  1353.     Time    firstTime, secondTime;
  1354.  
  1355.     /*
  1356.      * Unfortunately there's no direct indicator of age in the PCB.
  1357.      * Instead, use the total time used by the process and all its
  1358.      * children as a crude approximation.
  1359.      */
  1360.  
  1361.     Time_Add(first->infoPtr->kernelCpuUsage,
  1362.          first->infoPtr->userCpuUsage, &firstTime);
  1363.     Time_Add(first->infoPtr->childKernelCpuUsage,
  1364.           firstTime, &firstTime);
  1365.     Time_Add(first->infoPtr->childUserCpuUsage,
  1366.         firstTime, &firstTime);
  1367.     Time_Add(second->infoPtr->kernelCpuUsage,
  1368.         second->infoPtr->userCpuUsage, &secondTime);
  1369.     Time_Add(second->infoPtr->childKernelCpuUsage,
  1370.         secondTime, &secondTime);
  1371.     Time_Add(second->infoPtr->childUserCpuUsage,
  1372.         secondTime, &secondTime);
  1373.     if Time_GT(secondTicks, firstTime) {
  1374.     return 1;
  1375.     } else {
  1376.     return -1;
  1377.     }
  1378. #endif
  1379.     return second->infoPtr->numWaitEvents - first->infoPtr->numWaitEvents;
  1380. }
  1381. @
  1382.  
  1383.  
  1384. 1.21
  1385. log
  1386. @flush stderr after writing to it.
  1387. @
  1388. text
  1389. @d19 1
  1390. a19 1
  1391. static char rcsid[] = "$Header: /sprite/src/cmds/ps/RCS/ps.c,v 1.20 90/03/29 15:47:36 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1392. d358 1
  1393. a358 1
  1394.             if (status != PROC_INVALID_PID) {
  1395. @
  1396.  
  1397.  
  1398. 1.20
  1399. log
  1400. @try to avoid printing 'UNUSED' for a process that died between the time
  1401. we found out about it and the time we asked a remote host about it.
  1402. @
  1403. text
  1404. @d19 1
  1405. a19 1
  1406. static char rcsid[] = "$Header: /sprite/src/cmds/ps/RCS/ps.c,v 1.19 89/11/09 12:44:10 mendel Exp Locker: douglis $ SPRITE (Berkeley)";
  1407. d241 1
  1408. @
  1409.  
  1410.  
  1411. 1.19
  1412. log
  1413. @Fixed bug with sun4c CPU utilization reporting.
  1414. @
  1415. text
  1416. @d19 1
  1417. a19 1
  1418. static char rcsid[] = "$Header: /sprite/src/cmds/ps/RCS/ps.c,v 1.18 89/11/07 12:47:29 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  1419. d259 14
  1420. a272 4
  1421.         if (status != SUCCESS) {
  1422.             fprintf(stderr, "Couldn't find migrated pid \"%x\": %s.\n",
  1423.                 info.peerProcessID, Stat_GetMsg(status));
  1424.         } else{
  1425. d350 12
  1426. a361 3
  1427.         if (status != SUCCESS) {
  1428.             fprintf(stderr, "Couldn't find migrated pid \"%x\": %s.\n",
  1429.                 infoPtr->peerProcessID, Stat_GetMsg(status));
  1430. @
  1431.  
  1432.  
  1433. 1.18
  1434. log
  1435. @Modified to use getpagesize() rather than VMMACH_PAGE_SIZE so ps would
  1436. work on family of machines such as sun4 and sun4c. 
  1437. @
  1438. text
  1439. @d19 1
  1440. a19 1
  1441. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.17 89/07/31 17:50:44 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1442. d160 1
  1443. a160 1
  1444. extern int     timer_IntOneSecond; /* ticks per second */
  1445. d187 1
  1446. d795 1
  1447. a795 1
  1448.     scaleFactor = timer_IntOneSecond;
  1449. @
  1450.  
  1451.  
  1452. 1.17
  1453. log
  1454. @handle billing rates
  1455. @
  1456. text
  1457. @d19 1
  1458. a19 1
  1459. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.16 89/06/12 15:51:43 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1460. d158 2
  1461. d186 2
  1462. d904 2
  1463. a905 2
  1464.     rss *= VMMACH_PAGE_SIZE/1024;
  1465.     size *= VMMACH_PAGE_SIZE/1024;
  1466. d1021 2
  1467. a1022 2
  1468.         totalSize += segBuf[i].numPages*(VMMACH_PAGE_SIZE/1024);
  1469.         totalRss += segBuf[i].resPages*(VMMACH_PAGE_SIZE/1024);
  1470. d1032 2
  1471. a1033 2
  1472.         sizes[i] += segBuf[i].numPages*(VMMACH_PAGE_SIZE/1024);
  1473.         rss[i] += segBuf[i].resPages*(VMMACH_PAGE_SIZE/1024);
  1474. d1037 6
  1475. a1042 6
  1476.         segBuf[VM_CODE].numPages*(VMMACH_PAGE_SIZE/1024),
  1477.         segBuf[VM_CODE].resPages*(VMMACH_PAGE_SIZE/1024),
  1478.         segBuf[VM_HEAP].numPages*(VMMACH_PAGE_SIZE/1024),
  1479.         segBuf[VM_HEAP].resPages*(VMMACH_PAGE_SIZE/1024),
  1480.         segBuf[VM_STACK].numPages*(VMMACH_PAGE_SIZE/1024),
  1481.         segBuf[VM_STACK].resPages*(VMMACH_PAGE_SIZE/1024),
  1482. @
  1483.  
  1484.  
  1485. 1.16
  1486. log
  1487. @follow migrated processes.
  1488. @
  1489. text
  1490. @d19 1
  1491. a19 1
  1492. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.15 89/03/24 16:01:07 ouster Exp Locker: douglis $ SPRITE (Berkeley)";
  1493. d520 47
  1494. d869 1
  1495. a869 1
  1496.     printf("USER     PID   %%CPU %%MEM  SIZE   RSS STATE   TIME COMMAND\n");
  1497. d903 1
  1498. a903 1
  1499.     printf("%-8.8s %5x %.8s %4.1f%6d%6d %s%7s %s\n",
  1500. d906 2
  1501. a907 2
  1502.         StateString(infoPtr), TimeString(infoPtr), 
  1503.         ArgString(argPtr, 50));
  1504. d909 1
  1505. a909 1
  1506.     printf("%-8.8s %5x %.8s %4s%6s%6s %s%7s %s\n",
  1507. d913 1
  1508. a913 1
  1509.         ArgString(argPtr, 50));
  1510. @
  1511.  
  1512.  
  1513. 1.15
  1514. log
  1515. @Only use winsize info if non-zero.
  1516. @
  1517. text
  1518. @d19 1
  1519. a19 1
  1520. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.14 89/02/22 11:35:29 jhh Exp $ SPRITE (Berkeley)";
  1521. d43 1
  1522. d98 5
  1523. d123 4
  1524. a126 2
  1525.     OPT_CONSTANT(MIG),    "m",        (char *) &printIndex,
  1526.         "Print out information related to process migration",
  1527. d134 3
  1528. a136 1
  1529.         "Next argument holds line width for output"
  1530. d220 1
  1531. a237 1
  1532.  
  1533. d247 14
  1534. d269 1
  1535. d317 1
  1536. a317 5
  1537.         /*
  1538.          * When printing info for migrated processes, output info only
  1539.          * for migrated processes.
  1540.          */
  1541.         if ((printIndex == MIG) &&
  1542. d322 1
  1543. d324 18
  1544. d368 49
  1545. @
  1546.  
  1547.  
  1548. 1.14
  1549. log
  1550. @Now uses new Proc_GetPCBInfo and Vm_GetSegInfo interfaces
  1551. @
  1552. text
  1553. @d19 1
  1554. a19 1
  1555. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.13 88/12/22 11:04:48 douglis Exp $ SPRITE (Berkeley)";
  1556. d179 2
  1557. a180 1
  1558.     if (ioctl(fileno(stdout), TIOCGWINSZ, (char *) &winsize) == 0) {
  1559. @
  1560.  
  1561.  
  1562. 1.13
  1563. log
  1564. @print NEW if for some reason the proc is in PROC_NEW state.
  1565. @
  1566. text
  1567. @d19 1
  1568. a19 1
  1569. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.12 88/11/14 13:00:38 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1570. d26 1
  1571. a35 3
  1572. #include <kernel/proc.h>
  1573. #include <kernel/vm.h>
  1574.  
  1575. d136 1
  1576. a136 1
  1577.     Proc_ControlBlock *pcbPtr;
  1578. d147 2
  1579. d208 1
  1580. a208 1
  1581.         Proc_ControlBlock pcb;
  1582. d219 2
  1583. a220 1
  1584.                      &pcb, &argString, &pcbsUsed);
  1585. d232 1
  1586. a232 1
  1587.         if (pid != pcb.processID) {
  1588. d239 1
  1589. a239 1
  1590.         (*(printProc[printIndex]))(&pcb, &argString);
  1591. d243 1
  1592. a243 1
  1593.     Proc_ControlBlock pcbs[NUM_PCBS];
  1594. d247 1
  1595. a247 1
  1596.     register Proc_ControlBlock *pcbPtr;
  1597. d254 2
  1598. a255 1
  1599.                  pcbs, argStrings, &pcbsUsed);
  1600. d268 3
  1601. a270 3
  1602.     for (i = 0, numToPrint = 0, pcbPtr = pcbs; i < pcbsUsed;
  1603.         i++, pcbPtr++) {
  1604.         if (pcbPtr->state == PROC_UNUSED) {
  1605. d276 1
  1606. a276 1
  1607.         if (pcbPtr->genFlags & PROC_KERNEL) {
  1608. d282 1
  1609. a282 1
  1610.         if ((!aFlag) && (uid != pcbPtr->effectiveUserID)) {
  1611. d286 1
  1612. a286 1
  1613.         if ((pcbPtr->state != PROC_SUSPENDED) || !(pcbPtr->genFlags
  1614. d296 2
  1615. a297 2
  1616.         !((pcbPtr->genFlags & PROC_FOREIGN)
  1617.           || (pcbPtr->state == PROC_MIGRATED))) {
  1618. d301 1
  1619. a301 1
  1620.         blocks[numToPrint].pcbPtr = pcbPtr;
  1621. d323 1
  1622. a323 1
  1623.         (*(printProc[printIndex]))(blocks[i].pcbPtr, blocks[i].argString);
  1624. d348 2
  1625. a349 2
  1626. TimeString(pcbPtr)
  1627.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block. */
  1628. d354 1
  1629. a354 1
  1630.     Time_Add(pcbPtr->userCpuUsage.time, pcbPtr->kernelCpuUsage.time, &sum);
  1631. d381 2
  1632. a382 2
  1633. StateString(pcbPtr)
  1634.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block. */
  1635. d384 1
  1636. a384 1
  1637.     switch (pcbPtr->state) {
  1638. d395 1
  1639. a395 1
  1640.         if (pcbPtr->event == -1) {
  1641. d417 1
  1642. a417 1
  1643.         if (pcbPtr->genFlags & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST)) {
  1644. d633 2
  1645. a634 2
  1646. PctCpuString(pcbPtr)
  1647.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block. */
  1648. d659 1
  1649. a659 1
  1650.     percent = pcbPtr->unweightedUsage;
  1651. d683 2
  1652. a684 2
  1653. PrintShort(pcbPtr, argPtr)
  1654.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1655. d695 2
  1656. a696 2
  1657.     printf("%5x %s%7s %s\n", pcbPtr->processID, StateString(pcbPtr),
  1658.         TimeString(pcbPtr), ArgString(argPtr, 20));
  1659. d717 2
  1660. a718 2
  1661. PrintLong(pcbPtr, argPtr)
  1662.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1663. d725 1
  1664. a725 1
  1665.     Vm_Segment segBuf[VM_NUM_SEGMENTS];
  1666. d740 1
  1667. a740 1
  1668.     if (pcbPtr->genFlags & PROC_KERNEL) {
  1669. d743 16
  1670. a758 5
  1671.     status = Vm_GetSegInfo(pcbPtr, 0, &(segBuf[1]));
  1672.     if (status != SUCCESS) {
  1673.         fprintf(stderr, "Couldn't read segment info for pid %x: %s\n",
  1674.             pcbPtr->processID, Stat_GetMsg(status));
  1675.         return;
  1676. a759 4
  1677.     rss = segBuf[VM_CODE].resPages + segBuf[VM_HEAP].resPages
  1678.         + segBuf[VM_STACK].resPages;
  1679.     size = segBuf[VM_CODE].numPages + segBuf[VM_HEAP].numPages
  1680.         + segBuf[VM_STACK].numPages;
  1681. d761 17
  1682. a777 8
  1683.     pctMem = rss;
  1684.     rss *= VMMACH_PAGE_SIZE/1024;
  1685.     size *= VMMACH_PAGE_SIZE/1024;
  1686.     pctMem = (pctMem*100.0)/vmStat.numPhysPages;
  1687.     printf("%-8.8s %5x %.8s %4.1f%6d%6d %s%7s %s\n",
  1688.         UserString(pcbPtr->effectiveUserID),
  1689.         pcbPtr->processID, PctCpuString(pcbPtr), pctMem, size, rss,
  1690.         StateString(pcbPtr), TimeString(pcbPtr), ArgString(argPtr, 50));
  1691. d798 2
  1692. a799 2
  1693. PrintIDs(pcbPtr, argPtr)
  1694.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1695. d812 1
  1696. a812 1
  1697.     if (pcbPtr->familyID == -1) {
  1698. d815 1
  1699. a815 1
  1700.     family = sprintf(storage, "%5x", pcbPtr->familyID);
  1701. d818 3
  1702. a820 3
  1703.         pcbPtr->processID, pcbPtr->parentID, family,
  1704.         UserString(pcbPtr->effectiveUserID), 
  1705.         UserString(pcbPtr->userID), TimeString(pcbPtr),
  1706. d842 2
  1707. a843 2
  1708. PrintVM(pcbPtr, argPtr)
  1709.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1710. d852 1
  1711. a852 1
  1712.     Vm_Segment segBuf[VM_NUM_SEGMENTS];
  1713. d866 1
  1714. a866 1
  1715.     if (pcbPtr->genFlags & PROC_KERNEL) {
  1716. d869 4
  1717. a872 2
  1718.     status = Vm_GetSegInfo(pcbPtr, 0, &(segBuf[1]));
  1719.     if (status != SUCCESS) {
  1720. d874 1
  1721. a874 1
  1722.         pcbPtr->processID, Stat_GetMsg(status));
  1723. d877 16
  1724. a892 8
  1725.     totalSize = totalRss = 0;
  1726.     for (i = VM_CODE; i < VM_NUM_SEGMENTS; i++) {
  1727.     totalSize += segBuf[i].numPages*(VMMACH_PAGE_SIZE/1024);
  1728.     totalRss += segBuf[i].resPages*(VMMACH_PAGE_SIZE/1024);
  1729.     if (segBuf[i].segNum >= TOTAL_SEGS) {
  1730.         fprintf(stderr, "Pid %x has %s segment %d:  too large.\n",
  1731.             pcbPtr->processID, names[i], segBuf[i].segNum);
  1732.         continue;
  1733. d894 13
  1734. a906 6
  1735.     if (segSeen[segBuf[i].segNum]) {
  1736.         continue;
  1737.     }
  1738.     segSeen[segBuf[i].segNum] = 1;
  1739.     sizes[i] += segBuf[i].numPages*(VMMACH_PAGE_SIZE/1024);
  1740.     rss[i] += segBuf[i].resPages*(VMMACH_PAGE_SIZE/1024);
  1741. a907 9
  1742.     printf("%5x%6d%6d%6d%6d%6d%6d%6d%6d %s\n",
  1743.         pcbPtr->processID,
  1744.         segBuf[VM_CODE].numPages*(VMMACH_PAGE_SIZE/1024),
  1745.         segBuf[VM_CODE].resPages*(VMMACH_PAGE_SIZE/1024),
  1746.         segBuf[VM_HEAP].numPages*(VMMACH_PAGE_SIZE/1024),
  1747.         segBuf[VM_HEAP].resPages*(VMMACH_PAGE_SIZE/1024),
  1748.         segBuf[VM_STACK].numPages*(VMMACH_PAGE_SIZE/1024),
  1749.         segBuf[VM_STACK].resPages*(VMMACH_PAGE_SIZE/1024),
  1750.         totalSize, totalRss, ArgString(argPtr, 54));
  1751. d936 2
  1752. a937 2
  1753. PrintMigration(pcbPtr, argPtr)
  1754.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1755. d948 2
  1756. a949 2
  1757.     if ((pcbPtr->genFlags & PROC_FOREIGN)
  1758.         || (pcbPtr->state == PROC_MIGRATED)) {
  1759. d951 4
  1760. a954 4
  1761.         pcbPtr->processID, StateString(pcbPtr),
  1762.         pcbPtr->genFlags, pcbPtr->event,
  1763.         HostString(pcbPtr->peerHostID),
  1764.         pcbPtr->peerProcessID,
  1765. d958 2
  1766. a959 2
  1767.         pcbPtr->processID, StateString(pcbPtr),
  1768.         pcbPtr->genFlags, pcbPtr->event,
  1769. d982 2
  1770. a983 2
  1771. PrintSignals(pcbPtr, argPtr)
  1772.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block containing
  1773. d998 1
  1774. a998 1
  1775.     if (pcbPtr->sigActions[i] == SIG_IGNORE_ACTION) {
  1776. d1000 1
  1777. a1000 1
  1778.     } else if (pcbPtr->sigActions[i] >> SIG_NUM_ACTIONS) {
  1779. d1004 2
  1780. a1005 2
  1781.     printf("%5x %8x %8x %8x %8x %s\n", pcbPtr->processID,
  1782.         pcbPtr->sigPendingMask, pcbPtr->sigHoldMask,
  1783. d1032 1
  1784. a1032 1
  1785.     i = second->pcbPtr->unweightedUsage - first->pcbPtr->unweightedUsage;
  1786. d1067 3
  1787. a1069 3
  1788.     Time_Add(first->pcbPtr->kernelCpuUsage.time,
  1789.          first->pcbPtr->userCpuUsage.time, &firstTime);
  1790.     Time_Add(first->pcbPtr->childKernelCpuUsage.time,
  1791. d1071 1
  1792. a1071 1
  1793.     Time_Add(first->pcbPtr->childUserCpuUsage.time,
  1794. d1073 3
  1795. a1075 3
  1796.     Time_Add(second->pcbPtr->kernelCpuUsage.time,
  1797.         second->pcbPtr->userCpuUsage.time, &secondTime);
  1798.     Time_Add(second->pcbPtr->childKernelCpuUsage.time,
  1799. d1077 1
  1800. a1077 1
  1801.     Time_Add(second->pcbPtr->childUserCpuUsage.time,
  1802. d1085 1
  1803. a1085 1
  1804.     return second->pcbPtr->numWaitEvents - first->pcbPtr->numWaitEvents;
  1805. @
  1806.  
  1807.  
  1808. 1.12
  1809. log
  1810. @pass PROC_MY_HOSTID to kernel when getting PCB info.  Changed MIG1/MIG2
  1811. to ->MIG and MIG, respectively.
  1812. @
  1813. text
  1814. @d19 1
  1815. a19 1
  1816. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.11 88/10/17 17:47:55 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1817. d410 3
  1818. @
  1819.  
  1820.  
  1821. 1.11
  1822. log
  1823. @changed -m option to list only migrated/foreign processes, similar to
  1824. -d option.
  1825. @
  1826. text
  1827. @d19 1
  1828. a19 1
  1829. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.10 88/08/25 12:33:12 nelson Exp Locker: douglis $ SPRITE (Berkeley)";
  1830. d218 2
  1831. a219 1
  1832.             Proc_PIDToIndex(pid), &pcb, &argString, &pcbsUsed);
  1833. d252 2
  1834. a253 2
  1835.     status = Proc_GetPCBInfo(0, NUM_PCBS-1, pcbs, argStrings,
  1836.         &pcbsUsed);
  1837. d406 1
  1838. a406 1
  1839.         return "MIG1 ";
  1840. d409 1
  1841. a409 1
  1842.         return "MIG2 ";
  1843. @
  1844.  
  1845.  
  1846. 1.10
  1847. log
  1848. @Changed to handle new proc table timer format.
  1849. @
  1850. text
  1851. @d19 1
  1852. a19 1
  1853. static char rcsid[] = "$Header: ps.c,v 1.9 88/08/07 14:57:22 ouster Exp $ SPRITE (Berkeley)";
  1854. d287 9
  1855. @
  1856.  
  1857.  
  1858. 1.9
  1859. log
  1860. @Wrong parameter usage for Opt_Parse.
  1861. @
  1862. text
  1863. @d19 1
  1864. a19 1
  1865. static char rcsid[] = "$Header: ps.c,v 1.8 88/08/05 21:38:29 ouster Exp $ SPRITE (Berkeley)";
  1866. d339 1
  1867. a339 1
  1868.     Time user, kernel, sum;
  1869. d342 1
  1870. a342 3
  1871.     Timer_TicksToTime(pcbPtr->userCpuUsage, &user);
  1872.     Timer_TicksToTime(pcbPtr->kernelCpuUsage, &kernel);
  1873.     Time_Add(user, kernel, &sum);
  1874. d1020 1
  1875. a1020 1
  1876.     Timer_Ticks firstTicks, secondTicks;
  1877. d1028 13
  1878. a1040 13
  1879.     Timer_AddTicks(first->pcbPtr->kernelCpuUsage,
  1880.         first->pcbPtr->userCpuUsage, &firstTicks);
  1881.     Timer_AddTicks(first->pcbPtr->childKernelCpuUsage,
  1882.         firstTicks, &firstTicks);
  1883.     Timer_AddTicks(first->pcbPtr->childUserCpuUsage,
  1884.         firstTicks, &firstTicks);
  1885.     Timer_AddTicks(second->pcbPtr->kernelCpuUsage,
  1886.         second->pcbPtr->userCpuUsage, &secondTicks);
  1887.     Timer_AddTicks(second->pcbPtr->childKernelCpuUsage,
  1888.         secondTicks, &secondTicks);
  1889.     Timer_AddTicks(second->pcbPtr->childUserCpuUsage,
  1890.         secondTicks, &secondTicks);
  1891.     if Timer_TickGT(secondTicks, firstTicks) {
  1892. @
  1893.  
  1894.  
  1895. 1.8
  1896. log
  1897. @Typo:  was "==", should have been "=".
  1898. @
  1899. text
  1900. @d19 1
  1901. a19 1
  1902. static char rcsid[] = "$Header: ps.c,v 1.7 88/08/05 18:23:04 ouster Exp $ SPRITE (Berkeley)";
  1903. d197 2
  1904. a198 1
  1905.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 1);
  1906. @
  1907.  
  1908.  
  1909. 1.7
  1910. log
  1911. @Added "-s" option.
  1912. @
  1913. text
  1914. @d19 1
  1915. a19 1
  1916. static char rcsid[] = "$Header: ps.c,v 1.6 88/08/05 16:47:28 ouster Exp $ SPRITE (Berkeley)";
  1917. d187 1
  1918. a187 1
  1919.         termEnv == "";
  1920. @
  1921.  
  1922.  
  1923. 1.6
  1924. log
  1925. @Change FAMILY to GROUP.
  1926. @
  1927. text
  1928. @d19 1
  1929. a19 1
  1930. static char rcsid[] = "$Header: ps.c,v 1.5 88/08/05 16:13:52 ouster Exp $ SPRITE (Berkeley)";
  1931. d45 2
  1932. a46 1
  1933. extern void PrintIDs(), PrintLong(), PrintMigration(), PrintShort(), PrintVM();
  1934. d54 1
  1935. d66 1
  1936. d84 1
  1937. d121 2
  1938. d924 45
  1939. @
  1940.  
  1941.  
  1942. 1.5
  1943. log
  1944. @Lint.
  1945. @
  1946. text
  1947. @d19 1
  1948. a19 1
  1949. static char rcsid[] = "$Header: ps.c,v 1.4 88/08/05 15:51:08 ouster Exp $ SPRITE (Berkeley)";
  1950. d774 1
  1951. a774 1
  1952.     printf("PID   PPID FAMILY USER     RUSER      TIME COMMAND\n");
  1953. @
  1954.  
  1955.  
  1956. 1.4
  1957. log
  1958. @First complete version now runs.
  1959. @
  1960. text
  1961. @d19 1
  1962. a19 1
  1963. static char rcsid[] = "$Header: ps.c,v 1.1 88/08/01 17:12:05 ouster Exp $ SPRITE (Berkeley)";
  1964. d31 1
  1965. d207 1
  1966. a207 1
  1967.         printf(stderr, "Bad process id \"%s\";  ignoring.\n", argv[i]);
  1968. a402 3
  1969.     default:
  1970.         return "?Huh?";
  1971.         break;
  1972. d404 1
  1973. a812 1
  1974.     static int code, heap, stack;
  1975. @
  1976.  
  1977.  
  1978. 1.3
  1979. log
  1980. @Intermediate check-in.
  1981. @
  1982. text
  1983. @d24 1
  1984. d44 1
  1985. a44 1
  1986. extern void PrintIDs(), PrintLong(), PrintShort(), PrintVM();
  1987. d51 1
  1988. d62 1
  1989. d79 1
  1990. d114 2
  1991. d533 64
  1992. d873 46
  1993. @
  1994.  
  1995.  
  1996. 1.2
  1997. log
  1998. @Intermediate checkin.
  1999. @
  2000. text
  2001. @d43 1
  2002. a43 1
  2003. extern void PrintLong(), PrintShort();
  2004. d48 2
  2005. d58 2
  2006. a70 1
  2007. #define NOSORT (int (*(()[]))()) NULL
  2008. d74 3
  2009. a76 1
  2010.     UsageSort
  2011. d85 5
  2012. d98 18
  2013. a115 4
  2014.     OPT_DOC, (char *) NULL, (char *) NULL, "This program prints out process status information.\nSynopsis:  \"ps [switches] [pid pid ...]\"\nCommand-line switches are:",
  2015.     OPT_TRUE, "a", (char *) &aFlag, "Print info for all users' processes\n\t\tDefault: only current user's processes",
  2016.     OPT_CONSTANT(LONG), "u", (char *) &printIndex, "Use long form of status printout",
  2017.     OPT_INT, "w", (char *) &lineWidth, "Next arg holds line width for output"
  2018. d129 7
  2019. d220 3
  2020. d231 1
  2021. d251 7
  2022. a257 3
  2023.     for (i = 0, numToPrint = 0; i < pcbsUsed; i++) {
  2024.         if (pcbs[i].state == PROC_UNUSED) {
  2025.         continue;
  2026. d259 7
  2027. a265 1
  2028.         if ((!aFlag) && (uid != pcbs[i].effectiveUserID)) {
  2029. d268 8
  2030. a275 1
  2031.         blocks[numToPrint].pcbPtr = &pcbs[i];
  2032. d294 3
  2033. d471 1
  2034. a471 2
  2035.  *    Given an process table entry, return a string identifying
  2036.  *    the user corresponding to the process's effective user id.
  2037. d484 2
  2038. a485 2
  2039. UserString(pcbPtr)
  2040.     Proc_ControlBlock *pcbPtr;    /* Pointer to control block. */
  2041. d503 1
  2042. a503 1
  2043.     entry = Hash_CreateEntry(&table, (Address) pcbPtr->effectiveUserID, &new);
  2044. d513 1
  2045. a513 1
  2046.     passwd = getpwuid(pcbPtr->effectiveUserID);
  2047. d638 1
  2048. a638 1
  2049.     int rss;
  2050. d643 1
  2051. a643 1
  2052.     printf("USER     PID   %%CPU %%MEM   RSS STATE   TIME COMMAND\n");
  2053. d651 114
  2054. d769 1
  2055. a769 1
  2056.     exit(1);
  2057. d771 33
  2058. a803 8
  2059.     rss = segBuf[VM_CODE].resPages + segBuf[VM_HEAP].resPages
  2060.         + segBuf[VM_STACK].resPages;
  2061.     pctMem = rss;
  2062.     rss *= VMMACH_PAGE_SIZE/1024;
  2063.     pctMem = (pctMem*100.0)/vmStat.numPhysPages;
  2064.     printf("%-8.8s %5x %.8s %4.1f%6d %s%7s %s\n", UserString(pcbPtr),
  2065.         pcbPtr->processID, PctCpuString(pcbPtr), pctMem, rss,
  2066.         StateString(pcbPtr), TimeString(pcbPtr), ArgString(argPtr, 44));
  2067. @
  2068.  
  2069.  
  2070. 1.1
  2071. log
  2072. @Initial revision
  2073. @
  2074. text
  2075. @d19 1
  2076. a19 1
  2077. static char rcsid[] = "$Header: proto.c,v 1.2 88/03/11 08:39:08 ouster Exp $ SPRITE (Berkeley)";
  2078. d22 2
  2079. d25 1
  2080. d30 2
  2081. d34 1
  2082. d43 1
  2083. a43 1
  2084. extern void PrintShort();
  2085. d46 2
  2086. a47 1
  2087.     PrintShort
  2088. d60 15
  2089. d78 3
  2090. a80 1
  2091. int aFlag = 0;
  2092. d89 3
  2093. a91 1
  2094.     OPT_TRUE, "a", (char *) &aFlag, "Print info for all user processes \n\t\tDefault: only current user's processes"
  2095. d128 1
  2096. d130 23
  2097. d172 2
  2098. a173 2
  2099.         status = Proc_GetPCBInfo(pid&0xff, pid&0xff, &pcb, &argString,
  2100.             &pcbsUsed);
  2101. d222 4
  2102. a225 4
  2103.        }
  2104.        blocks[numToPrint].pcbPtr = &pcbs[i];
  2105.        blocks[numToPrint].argString = &argStrings[i];
  2106.        numToPrint++;
  2107. d229 1
  2108. a229 2
  2109.          * Sort the processes according to some relevant metric (no-op
  2110.      * for now).
  2111. d232 5
  2112. d286 239
  2113. d550 1
  2114. d552 138
  2115. a689 2
  2116.     printf("%5x %s %s\n", pcbPtr->processID, TimeString(pcbPtr),
  2117.         argPtr->argString);
  2118. @
  2119.